﻿using System;
using System.Drawing;
using System.Collections.Generic;

namespace Maze
{
    public class Player
    {
        public const int StartScore = 5;
        public const int MovementCost = 1;

        private Point location;
        private PathFinder pathFinder;
        private int score;
        private Point lastSquare = new Point(-1, -1);

        public delegate void PlayerScoreHandler(int score);
        public event PlayerScoreHandler PlayerScoreChangedEvent;

        public Player(Point startSquare, PathFinder pathFinder)
        {
            this.location = MazeForm.SquareToPixels(startSquare);
            this.pathFinder = pathFinder;
            this.score = Player.StartScore;
            this.lastSquare = startSquare;
        }

        public Point Location
        {
            get
            {
                return this.location;
            }
        }

        public int Score
        {
            get
            {
                return this.score;
            }
            set
            {
                this.score = value;
                if (this.PlayerScoreChangedEvent != null)
                {
                    this.PlayerScoreChangedEvent(this.score);
                }
            }
        }

        public void GoToSquare(Point square)
        {
            if (this.pathFinder.CurrentPath.Count > 0)
            {
                Point nextSquare = this.pathFinder.CurrentPath.First.Value;
                this.pathFinder.CurrentPath.Clear();
                this.pathFinder.Find(nextSquare, square);
                if (this.pathFinder.CurrentPath.First.Value != this.lastSquare)
                {
                    // We need to readd our previous "location"
                    this.pathFinder.CurrentPath.AddFirst(nextSquare);
                }
            }
            else
            {
                this.pathFinder.Find(MazeForm.PixelsToSquare(this.location), square);
            }

            this.Score -= Player.MovementCost;
        }

        public void Update(Board board)
        {
            this.Update(1, board);
        }

        public void Update(int divider, Board board)
        {
            if (this.pathFinder.CurrentPath.Count > 0)
            {
                Point square = this.pathFinder.CurrentPath.First.Value;
                Point point = MazeForm.SquareToPixels(square);

                this.location.X += Math.Sign(point.X - this.location.X) * (MazeForm.SquareSize.Width / divider);
                this.location.Y += Math.Sign(point.Y - this.location.Y) * (MazeForm.SquareSize.Height / divider);

                if (this.location == point)
                {
                    if (board[square] == SQ.C)
                    {
                        this.Score += MazeForm.CoinValue;
                        board[square] = SQ.O;
                    }
                    this.pathFinder.CurrentPath.RemoveFirst();
                    this.lastSquare = square;
                }

            }
        }

        public bool CollidesWith(Enemy enemy)
        {
            Size distance = new Size(Math.Abs(enemy.Location.X - this.location.X), Math.Abs(enemy.Location.Y - this.location.Y));
            int distanceSquared = distance.Width * distance.Width + distance.Height * distance.Height;

            return (distanceSquared < (MazeForm.SquareSize.Width * MazeForm.SquareSize.Height));
        }

        public bool IncludedInPath(Point square)
        {
            foreach (Point p in this.pathFinder.CurrentPath)
            {
                if (p == square)
                {
                    return true;
                }
            }

            return false;
        }
    }
}
